package com.px.user.controller;

import com.google.common.collect.ImmutableMap;
import com.px.common.core.RespCode;
import com.px.common.core.Response;
import com.px.common.util.FastUtil;
import com.px.user.entity.*;
import com.px.user.mapper.*;
import com.px.user.model.*;
import com.px.user.service.AdminOpsService;
import com.px.user.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.Authorization;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.math.BigDecimal;
import java.security.Principal;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Validated
@RestController
@RequestMapping("/profile")
@Api(value = "用户管理", tags = {"用户管理"})
public class UserController {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private InviteCodeMapper inviteCodeMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private RewardMapper rewardMapper;

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private RoomMapper roomMapper;

    @Autowired
    private AdminOpsMapper adminOpsMapper;

    @Autowired
    private HttpServletRequest httpServletRequest;

    @Autowired
    private AdminOpsService adminOpsService;


    @PostMapping("/sendSms/{code}")
    @ApiOperation(value = "注册短信", notes = "游客使用", tags = {"短信"})
    public Response<Long> sendSms(
            @ApiParam(value = "邀请码", example = "xxx") @NotBlank @PathVariable("code") String code,
            @RequestBody Sms sms) {
        InviteCode inviteCode = inviteCodeMapper.findByCode(code);
        if (inviteCode == null)
            return Response.fail(RespCode.INVITE_CODE_INVALID, null);

        userService.sendSms(sms);
        return Response.success(sms.getId());
    }

    @PostMapping("/inviteCode/{id}")
    @PreAuthorize("hasAnyAuthority('ROOMADMIN')")
    @ApiOperation(value = "邀请码创建", authorizations = {@Authorization(value = "token")}, tags = {"邀请码"})
    public Response<InviteCode> inviteCodePost(
            @ApiParam(value = "房间ID", example = "2") @PathVariable("id") Long id, Principal principal) {
        InviteCode inviteCode = new InviteCode();
        inviteCode.setFromUserId(Long.valueOf(principal.getName()));
        inviteCode.setRoomId(id);

        //inviteCode.setCode(UUID.randomUUID().toString().replace("-", ""));
        //inviteCode.setCode(Long.toHexString(inviteCode.getId()));
        inviteCodeMapper.insert(inviteCode);
        inviteCode.setCode(getCode());
        inviteCodeMapper.updateById(inviteCode);
        return Response.success(inviteCode);
    }

    //生成随机数
    public String getCode(){
        Random rand=new Random();//生成随机数
        String cardNnumer="";
        for(int a=0;a<8;a++){
            cardNnumer+=rand.nextInt(10);//生成6位数字
        }
        return cardNnumer;
    }

    @GetMapping("/inviteCode")
    @PreAuthorize("hasAnyAuthority('TEACHER','ROOMADMIN')")
    @ApiOperation(value = "邀请码获取", authorizations = {@Authorization(value = "token")}, notes = "老师/管理员使用", tags = {"邀请码"})
    public Response<List<InviteCode>> inviteCodeGet(Principal principal) {
        List<InviteCode> inviteCodes = inviteCodeMapper.getInviteCode(Long.valueOf(principal.getName()));
        return Response.success(inviteCodes);
    }

    @DeleteMapping("/inviteCode/{id}")
    @PreAuthorize("hasAnyAuthority('TEACHER','ROOMADMIN')")
    @ApiOperation(value = "邀请码删除", authorizations = {@Authorization(value = "token")}, notes = "老师/管理员使用", tags = {"邀请码"})
    public Response inviteCodeDelete(@ApiParam(value = "邀请码ID", example = "2") @PathVariable("id") Long id,
                                     Principal principal) {
        inviteCodeMapper.delete(ImmutableMap.of("id", id, "fromUserId", principal.getName()));
        return Response.success(null);
    }

    /*
    * 前端用户注册
    * */
    @PostMapping("/join/{code}")
    @ApiOperation(value = "注册", notes = "游客使用", tags = {"用户"})
    public Response<Long> join(
            @NotEmpty @ApiParam(value = "邀请码", example = "xxx") @PathVariable("code") String code,
            @Validated(ActionModel.Insert.class) @RequestBody JoinModel joinModel) {
        if (!userService.isSmsValid(joinModel.getPhone(), joinModel.getSms()))
            return Response.fail(RespCode.SMS_ERROR, null);

        InviteCode inviteCode = inviteCodeMapper.findByCode(code);
        if (inviteCode == null)
            return Response.fail(RespCode.INVITE_CODE_INVALID, null);

        User user = new User();
        user.setDisabled(0);
        user.setIp(FastUtil.getClientIP(httpServletRequest));
        user.setNickname(joinModel.getNickname());
        user.setAvatar(userMapper.randomAvatar());
        user.setUsername(joinModel.getPhone());
        user.setIsRobot(0);  //默认非机器人：0
        user.setPassword(user.passwordEncode(joinModel.getPassword()));
        user.setRoles(user.roles2json("CLIENT"));
        user.setSource("sms-reg");
        user.setInviteRoomId(inviteCode.getRoomId());
        user.setIsVirtual(0);
        userMapper.insert(user);

        return Response.success(user.getId());
    }

    @GetMapping
    @ApiOperation(value = "用户详情", authorizations = {@Authorization(value = "token")}, tags = {"用户"})
    public Response<User> userGet(
            @ApiParam(value = "截止时间", example = "1566805792293") @RequestParam(value = "beforeTime", required = false) Long beforeTime,
            Principal principal) {
        Timestamp tBeforeTime;
        if (beforeTime == null)
            tBeforeTime = new Timestamp(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(7));
        else
            tBeforeTime = new Timestamp(beforeTime);

        String userId = principal.getName();
        Optional<User> opt = userRepository.findById(Long.valueOf(userId));
        if (opt.isPresent()) {
            User user = opt.get();
            List<Course> courses = courseMapper.findByTeacherId(
                    Course.builder().teacherId(Long.valueOf(userId)).qend(tBeforeTime).build());
            courses.forEach(c -> c.setRoomIds(c.json2roomIds(c.getRoomIds())));
            user.setCourses(courses);
            user.setRoles(user.json2roles(user.getRoles()));
//            if (user.getRoles().contains("TEACHER")) {
//                user.setRoomIds(roomMapper.findListByUserId(Long.valueOf(userId)));
//            }
            if (user.getRoles().contains("ROOMADMIN")) {
                user.setAdminRoomIds(roomMapper.findListByAdminId(Long.valueOf(userId)));
            }
            return Response.success(user);
        } else
            return Response.fail(RespCode.ACCOUNT_NOT_EXIST, null);
    }

    @GetMapping("/teacher/{id}")
    @ApiOperation(value = "讲师信息查询", tags = {"用户"})
    public Response<User> teacherGet(@ApiParam(value = "讲师ID", example = "2") @PathVariable("id") Long id) {
        User user = userMapper.findByTeacherId(id);
        if (user == null)
            return Response.success(null);
        user.setRoles(user.json2roles(user.getRoles()));
        return Response.success(user);
    }

    @PutMapping
    @ApiOperation(value = "更新用户详情", authorizations = {@Authorization(value = "token")}, notes = "登录后使用", tags = {"用户"})
    public Response userPut(@RequestBody User user, Principal principal) {
        user.setId(Long.valueOf(principal.getName()));
        user.setUsername(null);
        user.setRoles(null);
        user.setPhone(null);
        user.setMoney(null);
        user.setDisabled(null);
        if (user.getPassword() != null)
            user.setPassword(user.passwordEncode(user.getPassword()));
        user.setIp(null);
        if (StringUtils.isNotEmpty(user.getPassword()))
            user.setPassword(user.passwordEncode(user.getPassword()));

        userMapper.update(user);

        return Response.success(null);
    }


    @PostMapping("/directRp/{id}")
    @ApiOperation(value = "定向红包", authorizations = {@Authorization(value = "token")}, notes = "登录后使用", tags = {"红包"})
    public Response directRpPost(@ApiParam(value = "收红包用户ID", example = "2") @PathVariable("id") Long id,
                                 @Validated(ActionModel.Insert.class) @RequestBody RedPack redPack,
                                 Principal principal) {
        if (redPack.getMoney().compareTo(BigDecimal.valueOf(0)) <= 0)
            return Response.fail(RespCode.PARA_ERROR, null);
        redPack.setCreatorId(Long.valueOf(principal.getName()));
        redPack.setAmount(1);
        redPack.setCategory(RedPackCategory.ONE.getStatus());
        userService.directRp(Long.valueOf(principal.getName()), id, redPack);
        return Response.success(null);
    }

    @GetMapping("/avatar")
    @ApiOperation(value = "头像列表", tags = {"头像"})
    public Response<List<Avatar>> avatarGet() {
        return Response.success(userMapper.findAllAvatar());
    }


    @PostMapping("/passwordSms")
    @ApiOperation(value = "修改/忘记密码短信", tags = {"密码", "短信"})
    public Response passwordSmsPost(@Validated(ActionModel.Insert.class) @RequestBody Sms sms) {
        userService.sendSms(sms);
        return Response.success(sms.getId());
    }

    @PutMapping("/password")
    @ApiOperation(value = "更新密码", notes = "游客使用", tags = {"密码"})
    public Response passwordPut(@Validated(ActionModel.Update.class) @RequestBody JoinModel joinModel) {
        if (!userService.isSmsValid(joinModel.getPhone(), joinModel.getSms()))
            return Response.fail(RespCode.SMS_ERROR, null);
        User user = new User();
        user.setUsername(joinModel.getPhone());
        user.setPassword(user.passwordEncode(joinModel.getPassword()));
        userMapper.updatePassword(user);
        return Response.success(null);
    }

    @PutMapping("/passwordByPass")
    @ApiOperation(value = "修改密码", authorizations = {@Authorization(value = "token")}, tags = {"密码"})
    public Response passwordByPassPut(@Validated(ActionModel.Update.class) @RequestBody PasswordModel passwordModel) {
        String password = userMapper.findByUsername(passwordModel.getPhone());
        if (new BCryptPasswordEncoder().matches(passwordModel.getOldPassword(), password)) {
            userMapper.updatePassword(User.builder()
                    .username(passwordModel.getPhone())
                    .password(new BCryptPasswordEncoder().encode(passwordModel.getPassword()))
                    .build());
        } else
            return Response.fail(RespCode.PASSWORD_ERROR, null);
        return Response.success(null);
    }

    @GetMapping("/rewardHis")
    @ApiOperation(value = "用户打赏礼物记录", authorizations = {@Authorization(value = "token")}, tags = {"礼物"})
    public Response<PagingResp<RewardHis>> userRewardGet(
            @ApiParam(value = "用户ID(管理员使用)", example = "1") @RequestParam(value = "fromUserId", required = false) Long fromUserId,
            @ApiParam(value = "开始时间戳", example = "1566805792293") @RequestParam(value = "start", required = false) Long qstart,
            @ApiParam(value = "结束时间戳", example = "1566805792293") @RequestParam(value = "end", required = false) Long qend,
            @ApiParam(value = "排序字段(倒序)", example = "updateTime") @RequestParam(value = "orderField", required = false, defaultValue = "createTime") String orderField,
            @ApiParam(value = "页码", example = "0") @RequestParam(value = "page", required = false, defaultValue = "0") @Min(0) Integer page,
            @ApiParam(value = "返回数量", example = "10") @RequestParam(value = "limit", required = false, defaultValue = "10") @Min(1) Integer limit,
            Authentication authentication) {
        RewardHis qRewardHis = RewardHis.builder()
                .fromUserId(fromUserId)
                .qstart(qstart == null ? null : new Timestamp(qstart))
                .qend(qend == null ? null : new Timestamp(qend))
                .orderField(orderField)
                .startIndex(page * limit)
                .limit(limit)
                .build();

        Collection roles = authentication.getAuthorities();
        SimpleGrantedAuthority admin = new SimpleGrantedAuthority("ADMIN");
        if (!roles.contains(admin))
            qRewardHis.setFromUserId(Long.valueOf(authentication.getName()));

        return Response.success(PagingResp.<RewardHis>builder()
                .itemCount(rewardMapper.pagingCount(qRewardHis))
                .items(rewardMapper.paging(qRewardHis))
                .build());
    }


    @PostMapping("/kickUser")
    @ApiOperation(value = "踢人记录", authorizations = {@Authorization(value = "token")}, tags = {"踢人"})
    public Response kickUserPost(@Validated(ActionModel.Insert.class) @RequestBody AdminOps adminOps,
                                 Authentication authentication) {
        adminOpsService.setRole(adminOps, authentication);
        adminOps.setUrl(httpServletRequest.getRequestURI());
        adminOpsMapper.insert(adminOps);
        return Response.success(null);
    }
}
